package org.light.limitedverb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Field;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.Type;
import org.light.exception.ValidateException;
import org.light.utils.DomainTokenUtil;
import org.light.utils.InterVarUtil;
import org.light.utils.TableStringUtil;
import org.light.utils.WriteableUtil;

public class CountSearchByFieldsRecords extends NoControllerVerb {
	protected static Logger logger = Logger.getLogger(CountSearchByFieldsRecords.class);
	@Override
	public Method generateDaoImplMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			if ("pgsql".equalsIgnoreCase(this.dbType)||"postgresql".equalsIgnoreCase(this.dbType)) {
				org.light.pgsql.verb.CountSearchByFieldsRecords sn = new org.light.pgsql.verb.CountSearchByFieldsRecords(this.domain);
				return sn.generateDaoImplMethod();
			}else {
				Method method = new Method();
				method.setStandardName("countSearch" + domain.getCapFirstPlural() + "ByFieldsRecords");
				method.setNoContainer(true);
				List<Writeable> list = new ArrayList<Writeable>();
				list.add(new Statement(100L, 1, "<select id=\"" + method.getLowerFirstMethodName() + "\" parameterType=\""
						+ this.domain.getFullName() + "\" resultType=\"int\">"));
				list.add(new Statement(200L, 2, "select count(*) countSum from " + domain.getDbPrefix()
						+ TableStringUtil.domainNametoTableName(domain)));
				list.add(new Statement(300L, 2, "where 1=1 "));
				long serial = 400L;
				Set<Field> fields = this.domain.getFieldsWithoutId();
				for (Field f : fields) {
					logger.debug("JerryDebug:"+this.domain.getStandardName()+":"+f.getFieldName()+":"+f.getFieldType());
					if (f.getFieldType().equalsIgnoreCase("string")) {
						list.add(new Statement(serial, 2, "<if test=\"" + f.getLowerFirstFieldName() + "!=null and "
								+ f.getLowerFirstFieldName() + "!='' \">"));
						list.add(new Statement(serial + 100, 3,
								"and " + DomainTokenUtil.changeDomainFieldtoTableColum(f.getLowerFirstFieldName())
										+ " LIKE CONCAT(CONCAT('%', #{" + f.getLowerFirstFieldName() + "}),'%')"));
					} else {
						list.add(new Statement(serial, 2, "<if test=\"" + f.getLowerFirstFieldName() + "!=null\">"));
						list.add(new Statement(serial + 100, 3,
								"and " + DomainTokenUtil.changeDomainFieldtoTableColum(f.getLowerFirstFieldName()) + " = #{"
										+ f.getLowerFirstFieldName() + "}"));
					}
					list.add(new Statement(serial + 200, 2, "</if>"));
					serial += 300L;
				}
				list.add(new Statement(serial, 1, "</select>"));
				method.setMethodStatementList(WriteableUtil.merge(list));
				return method;
			}
		}
	}

	@Override
	public String generateDaoImplMethodString() throws Exception {
		if (this.denied)
			return null;
		else {
			Method m = this.generateDaoImplMethod();
			String s = m.generateMethodString();
			return s;
		}
	}

	@Override
	public String generateDaoImplMethodStringWithSerial() throws Exception {
		if (this.denied)
			return null;
		else {
			Method m = this.generateDaoImplMethod();
			m.setContent(m.generateMethodContentStringWithSerial());
			m.setMethodStatementList(null);
			return m.generateMethodString();
		}
	}

	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		if (this.denied)
			return null;
		else {
			Method method = new Method();
			method.setStandardName("countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords");
			method.setReturnType(new Type("Integer"));
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addSignature(new Signature(1, this.domain.getLowerFirstDomainName(), this.domain.getType(),
					this.domain.getPackageToken()));
			method.setThrowException(true);
			return method;
		}
	}

	@Override
	public String generateDaoMethodDefinitionString() throws Exception {
		if (this.denied)
			return null;
		else {
			return generateDaoMethodDefinition().generateMethodDefinition();
		}
	}

	@Override
	public Method generateServiceMethodDefinition() throws Exception {
		if (this.denied)
			return null;
		else {
			Method method = new Method();
			method.setStandardName("countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords");
			method.setReturnType(new Type("Integer"));
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addSignature(new Signature(1, this.domain.getLowerFirstDomainName(), this.domain.getType()));
			method.setThrowException(true);

			return method;
		}
	}

	@Override
	public String generateServiceMethodDefinitionString() throws Exception {
		if (this.denied)
			return null;
		else {
			return generateServiceMethodDefinition().generateMethodDefinition();
		}
	}

	@Override
	public Method generateServiceImplMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			Method method = new Method();
			method.setStandardName("countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords");
			method.setReturnType(new Type("Integer"));
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDaoSuffix() + "."
					+ this.domain.getStandardName() + "Dao");
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getServiceSuffix() + "."
					+ this.domain.getStandardName() + "Service");
			method.addSignature(new Signature(1, this.domain.getLowerFirstDomainName(), this.domain.getType()));
			method.setThrowException(true);
			method.addMetaData("Override");

			Method daomethod = this.generateDaoMethodDefinition();
			List<Writeable> list = new ArrayList<Writeable>();
			list.add(new Statement(1000L, 2, "return "
					+ daomethod.generateStandardServiceImplCallString(InterVarUtil.DB.dao.getVarName()) + ";"));
			method.setMethodStatementList(WriteableUtil.merge(list));

			return method;
		}
	}

	@Override
	public String generateServiceImplMethodString() throws Exception {
		if (this.denied)
			return null;
		else {
			return generateServiceImplMethod().generateMethodString();
		}
	}

	@Override
	public String generateServiceImplMethodStringWithSerial() throws Exception {
		if (this.denied)
			return null;
		else {
			Method m = this.generateServiceImplMethod();
			m.setContent(m.generateMethodContentStringWithSerial());
			m.setMethodStatementList(null);
			return m.generateMethodString();
		}
	}

	public CountSearchByFieldsRecords(Domain domain) throws ValidateException {
		super();
		this.domain = domain;
		this.dbType = "MariaDB";
		this.denied = domain.isVerbDenied("SearchByFieldsByPage");
		this.verbName = "countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords";
	}
	
	public CountSearchByFieldsRecords(Domain domain,String dbType) throws ValidateException {
		super();
		this.domain = domain;
		this.dbType = dbType;
		this.denied = domain.isVerbDenied("SearchByFieldsByPage");
		this.verbName = "countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords";
	}

	public CountSearchByFieldsRecords() {
		super();
		this.dbType = "MariaDB";
	}
	
	public CountSearchByFieldsRecords(String dbType) {
		super();
		this.dbType = dbType;
	}

}
